home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-08-18 | 39.3 KB | 1,184 lines |
- (* :Title: z-Transform Rule Base *)
-
- (* :Authors: Brian Evans, James McClellan *)
-
- (*
- :Summary: To take the forward, multi-dimensional z-transform
- of a discrete-time expression of mathematical
- and signal processing structures.
- *)
-
- (* :Context: SignalProcessing`Digital`ZTransform` *)
-
- (* :PackageVersion: 2.7 *)
-
- (*
- :Copyright: Copyright 1989-1991 by Brian L. Evans
- Georgia Tech Research Corporation
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is
- hereby granted, provided that the above copyright notice
- appear in all copies and that both that copyright notice and
- this permission notice appear in supporting documentation,
- and that the name of the Georgia Tech Research Corporation,
- Georgia Tech, or Georgia Institute of Technology not be used
- in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission. Georgia
- Tech makes no representations about the suitability of this
- software for any purpose. It is provided "as is" without
- express or implied warranty.
- *)
-
- (* :History: *)
-
- (* :Keywords: z-transform, region of convergence *)
-
- (*
- :Source: Muth, E. J. {Transform Methods}. 1977
-
- Oppenheim and Schafer. {Digital Signal Processing}. 1973.
-
- Clements, M., and Pease, J. "On Causal Linear Phase IIR
- Digital Filters". Transactions of Acoustics, Speech, and
- Signal Processing (ASSP). April 1989
-
- Dungeon and Mersereau. {Multidimensional Signal
- Processing}. 1984.
- *)
-
- (*
- :Warning: This package stuff is nasty; reminds me of Lisp, except
- that Lisp had package-independent keywords like :hi.
- Remember, that only those symbols with a ::usage are
- exported.
- Keep all conditional clauses on the same line; breaking
- long clauses onto separate lines with RETURNS will
- cost you (package context is not reset to Global)
- I do rely on three variables that are global only to
- this package-- completeOptions, dialogueAllFlag, and
- generatePairsFlag. The first maintains a list of the
- complete set of options. The second specifies the
- level of dialogue. The third indicates whether or not
- to simplify the resulting transform. I'm really sorry
- for doing this--- I know that it is bad programming.
- *)
-
- (* :Mathematica Version: 1.2 or 2.0 *)
-
- (* :Limitation: *)
-
- (* :Discussion: All new functions have usage information.
- Local state rules base with a total of 76 rules:
- I. multidimensional hooks 9 rules
- II. rational transforms 15 rules
- III. non-rational transform pairs 7 rules
- IV. transform properties 13 rules
- V. transforms of DSP structures 22 rules
- VI. transform strategies 10 rules
-
- The only purpose to the multidimensional hook rules is to track
- the region of convergence for non-separable functions. Without
- these rules, the z-transform rule base would still properly
- compute the z-transform function. Otherwise, the DTFTransform
- would not work properly for functions like (6/7)^n1 (9/10)^n2
- Impulse[n1 - n2] Step[n1, n2] with respect to the variables n1
- and n2.
-
- At each step in the z-transform rules base, the current expression
- has a local state associated with it. This state consists of
- a list of five boolean values. Each boolean value is associated
- with a strategy. If an element is True, then that strategy has not
- been tried yet; if False, then that strategy has already been tried,
- and it will not be tried again. Thus, local state is used to
- prevent infinite loops which would be caused by the repetitive
- application of certain strategy rules. See the section S T A T E
- D E F I N I T I O N below and see section VI of the rules.
-
- MyZTransform[ f[n], n, z, state, nlist, zlist, options ] is similar
- to ZTransform. The one-dimensional z-transform of f[n] will be
- returned as a list of three pieces of data: X(z), Rminus, Rplus.
- The current dimension being transformed is indicated by atoms n
- and z; nlist contains the list of all time index variables
- used in f[n]; and zlist contains the z-transform variables.
- Note that ZTransform drives the rule base defined by MyZTransform
- when computing the forward z-transform.
-
- multidROC[zexpr, oldzexpr] accumulates region of convergence
- information. That is, ROC of the current z-transform is only
- one-dimensional; therefore, zexpr must be updated with the
- cumulative ROC information in oldzexpr.
- *)
-
-
- (* :Functions: ZTransform *)
-
-
-
- (* B E G I N P A C K A G E *)
-
- BeginPackage[ "SignalProcessing`Digital`ZTransform`",
- "SignalProcessing`Digital`ZSupport`",
- "SignalProcessing`Support`TransSupport`",
- "SignalProcessing`Support`ROC`",
- "SignalProcessing`Support`FilterSupport`",
- "SignalProcessing`Support`SigProc`",
- "SignalProcessing`Support`SupCode`" ]
-
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- Off[ General::spell ];
- Off[ General::spell1 ] ];
-
-
- (* U S A G E I N F O R M A T I O N *)
-
- ZTransform::usage =
- "ZTransform[e,n] or ZTransform[e,n,z] gives the z-transform of \
- the expression e, which is a function of n, by returning an object \
- of three slots which is tagged by ZTransData: \
- <z-transform>, <rminus>, <rplus>, and <z-variables>. \
- The Region of Convergence (ROC) is <rminus> < |z| < <rplus>. \
- Note that the returned ROC is either the actual ROC or a subset \
- of the actual ROC. \
- In two dimensions, ZTransform[e, {n1, n2}, {z1, z2}], is the same as \
- ZTransform [ ZTransform [e, n1, z1], n2, z2 ]. \
- This notation extends naturally to higher dimensions."
-
- (* E N D U S A G E I N F O R M A T I O N *)
-
-
- Begin[ "`Private`" ]
-
-
- (* M E S S A G E S *)
-
- ZTransform::notexist =
- "The function `` does not have a valid z-transform with respect to ``."
-
- ZTransform::badROC = "Improper region of convergence in ``."
-
-
- (* U S E R I N T E R F A C E *)
-
- (* Z Operator *)
- Unprotect[Z]
- Z/: TheFunction[ Z[n_, z_][f_] ] := ZTransform[f, n, z]
- Protect[Z]
-
- (* ZTransform *)
- ZTransform/: Options [ ZTransform ] :=
- { Definition -> False, Dialogue -> True,
- Simplify -> True, TransformLookup -> {} }
-
- ZTransform[f_] :=
- ztransformdriver[ Options[ZTransform], f ]
- ZTransform[f_, n_] :=
- ztransformdriver[ Options[ZTransform], f, n ]
- ZTransform[f_, n_, z_] :=
- ztransformdriver[ Options[ZTransform], f, n, z ]
- ZTransform[f_, n_, z_, op__] :=
- ztransformdriver[ ToList[op] ~Join~ Options[ZTransform], f, n, z ]
-
- (* data global to only this package, see :Warning: above *)
- completeOptions = {}
- dialogueAllFlag = False
- indentationString = ""
- simplifyFlag = False
-
- (* validvarQ *)
- validvarQ[ x_Symbol ] := True
- validvarQ[ x_List ] := Apply[And, Map[VariableQ, x]]
- validvarQ[ x_ ] := False
-
- (* Interface support *)
- ztransformdriver[op_, f_, n_, rest___] :=
- Message[ Transform::badvar, "discrete-time", ZTransform, n ] /;
- ! validvarQ[n]
-
- ztransformdriver[op_, f_, n_, z_] :=
- Message[ Transform::badvar, "z", ZTransform, z ] /;
- ! validvarQ[z]
-
- ztransformdriver[op_, f_, n_, z_] :=
- Block [ {},
-
- (* Set all global variables right here *)
- completeOptions = op;
- dialogueAllFlag = SameQ[Replace[Dialogue, op], All];
- simplifyFlag = TrueQ[Replace[Simplify, op]];
-
- (* Do the transform *)
- cleanup [ ztransform[op, f, n, z], InformUserQ[op] ] ]
-
- ztransform[op_, args__] :=
- Replace [ ztrans[op, args], ZTransformInterfaceRules ]
-
- ZTransformInterfaceRules = {
- ztrans[op_, e_] :> e /; ZTransformQ[e],
-
- ztrans[op_, e_] :>
- Message[Transform::novariables, "n (time)", GetVariables[e]],
-
- ztrans[op_, e_, n_] :> e /; ZTransformQ[e],
-
- ztrans[op_, e_, n_] :>
- ztransform[op, e, n, DummyVariables[Length[n], Global`z]],
-
- ztrans[op_, e_, n_, zl_] :>
- MultiDTransform[ MakeZObject, ztransform,
- ZTransformQ, e, n, z, zl, op ] /;
- ListQ[n] && ( AtomQ[zl] || ListQ[zl] ),
-
- ztrans[op_, e_, n_, z_] :> ztransform[op, e, n, z, {n}, {z}] /;
- AtomQ[n] && AtomQ[z],
-
- ztrans[op_, e_, n_, z_, nlist_, zlist_] :>
- If [ SameQ[ToList[ZVariables[e]], zlist],
- e,
- multidROC[ztransform[op, TheFunction[e], n, z, nlist, zlist],
- e] ] /;
- ZTransformQ[e] && AtomQ[n] && AtomQ[z],
-
- ztrans[op_, e_, n_, z_, nlist_, zlist_] :>
- MakeZObject[ MyZTransform [ e, n, z, nlist, zlist, op ], z ] /;
- ! ZTransformQ[e] && AtomQ[n] && AtomQ[z]
- }
-
- (* cleanup passes every subexpression of the transform through explain *)
- cleanup[Null, flag_] := flag
-
- cleanup[trans_, dialogue_] :=
- Block [ {dialflag, rminus, rplus, trace, valid, validROC = True},
- dialflag = InformUserQ[dialogue];
- trace = SameQ[dialogue, All];
- valid = SameQ[Head[trans], ZTransData];
- If [ valid,
- rminus = SPSimplify[ GetRMinus[trans] ];
- rplus = SPSimplify[ GetRPlus[trans] ];
- validROC = Apply[And,
- Thread[ToList[rminus] < ToList[rplus]]] ];
- Which [ TrueQ[! validROC],
- Message[ZTransform::badROC, trans],
- valid && simplifyFlag,
- SPSimplify[ trans, Dialogue -> trace ],
- dialflag && ! valid,
- Scan[explain, trans, Infinity];
- trans,
- True,
- trans ] ]
-
- (* explain tells the user about those parts of the *)
- (* "time"-function which do not have a transform. *)
- explain[ forwardz[f_, n_, rest__] ] :=
- Message[ Transform::incomplete, "forward z-transform", f, n ]
-
-
- (* S U P P O R T I N G R O U T I N E S *)
-
- absDialogue[f_, n_, options_] :=
- Block [ {dialogue, result},
- dialogue = InformUserQ[options];
- result = ( f /. {Abs[a_. n] :> Abs[a] n} ) Step[n] +
- ( f /. {Abs[b_. n] :> - Abs[b] n} ) Step[-n - 1];
-
- If [ dialogue,
- Print[ "( after rewriting the two-sided expression" ];
- Print[ " ", f ];
- Print[ " as a left-sided plus a right sided sequence" ];
- Print[ " ", result, " )" ] ];
-
- result ]
-
- addZ[t1_, t2_] := AddT[ZForm, t1, t2]
-
- allROC[t_] := Transform[TheFunction[t], 0, Infinity] /; ZForm[t]
-
- antiCausalZ[t_, z_] :=
- Transform[ TheFunction[t] /. z -> z^-1,
- 1 / GetRPlus[t], 1 / GetRMinus[t] ] /;
- ZForm[t]
-
- applyDefinition[x_, n_, z_, s_, nlist_, zlist_, op_] :=
- Block [ {newx, state, summhead, trans},
- state = SetStateField[s, definitionfield, False];
- summhead = If [ TrueQ[ $VersionNumber >= 2.0 ],
- Needs[ "Algebra`SymbolicSum`" ];
- Algebra`SymbolicSum,
- Needs[ "Algebra`GosperSum`" ];
- Algebra`GosperSum ];
- newx = ToDiscrete [ TheFunction[x] ];
- trans = summhead[newx z^(-n), {n, -Infinity, Infinity}];
- If [ SameQ[Head[trans], summhead],
- forwardz[x, n, z, state, nlist, zlist, op],
- TransformDialogue[ Definition, op, summhead, x,
- Transform[trans, 0, Infinity] ] ] ]
-
- computeDownsamplingFactor[f_, n_] := Numerator[ ScalingFactor[f, n] ]
-
- conjZ[t_, z_] := ConjT[ZForm, t, z]
-
- convolveZ[convop_, t1_, t2_] := ConvolveT[ZForm, convop, t1, t2]
-
- (* diagonalResamplingMatrixQ *)
- diagonalResamplingMatrixQ[mat_] := False /; ! MatrixQ[mat]
- diagonalResamplingMatrixQ[mat_] :=
- Block [ {cond = False, diag, dims, i},
- dims = Dimensions[mat];
- If [ dims[[1]] == dims[[2]],
- diag = Table[ mat[[i,i]], { i, 1, dims[[1]] } ];
- cond = Apply[And, Map[isinteger, diag] ] &&
- SameQ[mat, DiagonalMatrix[diag]] ];
- cond ]
-
-
- downsampledTransform[trans_, z_, m_] :=
- Block [ {fztrans, k},
- fztrans = trans /. z -> ( Exp[-2 Pi I k / m] z^(1/m) );
- If [ IntegerQ[m],
- 1/Abs[m] Sum[fztrans, {k, 0, Abs[m]-1}],
- k = Unique["k"];
- 1/Abs[m] Summation[k, 0, Abs[m]-1, 1][fztrans] ] ]
-
- downsampleZ[ztrans_, z_Symbol, m_] :=
- Block [ {fz, fztrans, k, rm, rp},
- rm = takeRealPower[ GetRMinus[ztrans], m ];
- rp = takeRealPower[ GetRPlus[ztrans], m ];
- fz = downsampledTransform[ TheFunction[ztrans], z, m ];
- Transform[fz, rm, rp] ] /;
- ZForm[ztrans]
-
- dz[t_, z_:Global`z, k_:1] :=
- Transform[ D[TheFunction[t], {z, k}], GetRMinus[t], GetRPlus[t] ] /;
- ZForm[t]
-
- (* fixUp: removes TransformLookup option from passed options *)
- fixUp[ op_ ] :=
- { Definition -> Replace[Definition, op],
- Dialogue -> Replace[Dialogue, op],
- Simplify -> Replace[Simplify, op] }
-
- integrateZ[t_, z_:Global`z] := IntegrateT[ZForm, t, z, z, Infinity]
-
- isinteger[x_] := Implies[ NumberQ[x], IntegerQ[x] ]
-
- isintegerMatrix[ x_ ] :=
- MatrixQ[x] && Apply[ SameQ, Dimensions[x] ] &&
- Apply[ And, Map[isinteger, Flatten[x]] ]
-
- lineImpulseMDZ[t_, z_, zlist_, nleft_] :=
- LineImpulsemDT[ZForm, t, z, zlist, nleft, Times]
-
- (* mDresamplingCheck *)
- mDresamplingCheck[separable, l_, n_, nvars_, nlist_] :=
- MyFreeQ[l, nvars] && SubsetQ[{n}, nvars, nlist] &&
- diagonalResamplingMatrixQ[l]
-
- mDresamplingCheck[Downsample, l_, n_, nvars_, nlist_] :=
- Block [ {cond},
- cond = MyFreeQ[l, nvars] && SubsetQ[{n}, nvars, nlist] &&
- MatrixQ[l] && Apply[SameQ, Dimensions[l]] &&
- Apply[ And, Map[IntegerQ, Flatten[l]] ];
- If [ cond, Needs[ "SignalProcessing`Digital`MDZTransform`" ] ];
- cond ]
-
- mDresamplingCheck[Upsample, l_, n_, nvars_, nlist_] :=
- Block [ {cond},
- cond = MyFreeQ[l, nvars] && SubsetQ[{n}, nvars, nlist] &&
- isintegerMatrix[l];
- If [ cond, Needs[ "SignalProcessing`Digital`MDZTransform`" ] ];
- cond ]
-
- multZ[t1_, t2_] := MultT[ZForm, t1, t2]
-
- multiplyByExponential[t_, aexp_, z_, c_, options_] :=
- Block [ {newrplus, rplus},
- rplus = GetRPlus[t];
- newrplus = If [ InfinityQ[rplus], Infinity, Abs[aexp] rplus ];
- Transform[ c TheFunction[t] /. z -> z / aexp,
- Abs[aexp] GetRMinus[t], newrplus ] ] /;
- ZForm[t]
-
- myZmultinomialLeftOver[f_, nvars__] :=
- myZmultinomialSupport[Apply[Times, Map[Factorial, {nvars}]^-1], f] [[2]]
-
- myZmultinomialQ[f_, nvars__] :=
- TrueQ [ myZmultinomialSupport[Apply[Times, Map[Factorial, {nvars}]^-1], f] [[1]] ]
-
- myZmultinomialSupport[factexpr_, f_. factexpr_] := { True, f }
-
- propagateOperator[ trans_, op_ ] :=
- Transform[ op[ TheFunction[trans] ],
- GetRMinus[trans],
- GetRPlus[trans] ] /;
- ZForm[trans]
-
- reallyDownsampledQ[f_, n_] :=
- Block [ {downfact},
- downfact = computeDownsamplingFactor[f, n];
- (! SameQ[downfact, 0]) && (! SameQ[downfact, 1]) &&
- Implies[ NumberQ[downfact], IntegerQ[downfact] ] ]
-
- SetAttributes[rootROC, {Listable}]
- rootROC[x_, 0, z_] := z
- rootROC[x_, y_, z_] := takeRealPower[x, 1/y]
-
- scaleZ[t_, c_] := ScaleT[ZForm, t, c]
-
- substituteforZ[t_, z_, newz_] := SubstituteForT[ZForm, t, z, newz]
-
- subZ[t1_, t2_] := SubT[ZForm, t1, t2]
-
- (* takeRealPower -- assume that both arguments are real-valued *)
- SetAttributes[ takeRealPower, { Listable } ]
- takeRealPower[ 0, r_ ] := 0
- takeRealPower[ Infinity, r_ ] := Infinity
- takeRealPower[ x_^b_, r_ ] := x^(b r) /; IntegerQ[b r]
- takeRealPower[ x_, r_ ] := x^r
-
- upsampleZ[ztrans_, z_Symbol, m_] :=
- Block [ {fz, rm, rp},
- rm = rootROC[ GetRMinus[ztrans], m, 1 ]; (* adjust ROC *)
- rp = rootROC[ GetRPlus[ztrans], m, 1 ];
- fz = TheFunction[ztrans] /. z -> z^m; (* adjust transform *)
- Transform[fz, rm, rp] ] /;
- ZForm[ztrans]
-
- Zdz[t_, z_:Global`z, k_:1] :=
- Block [ {count, expr},
- expr = TheFunction[t];
- For [ count = 0, count < k, count++,
- expr = - z SPSimplify[D[expr, z]] ];
- Transform[ expr, GetRMinus[t], GetRPlus[t] ] ] /;
- ZForm[t] && IntegerQ[k] && ( k >= 0 )
-
-
- (* R E G I O N O F C O N V E R G E N C E *)
-
- multidROC[zexpr_, oldz_] :=
- MakeZObject[ { zexpr[[1]],
- Append[ ToList[ GetRMinus[oldz] ], GetRMinus[zexpr] ],
- Append[ ToList[ GetRPlus[oldz] ], GetRPlus[zexpr] ] },
- Append[ ToList[ZVariables[oldz]], ZVariables[zexpr] ] ] /;
- ZTransformQ[zexpr] && ZTransformQ[oldz]
-
-
- (* S T A T E D E F I N T I O N *)
-
- (* in the order of their appearance in the rule base *)
-
- factorfield = 1 (* apply Factor[] to denominator *)
- expandfield = 2 (* apply Expand[] to expression *)
- expandallfield = 3 (* apply ExpandAll[] to expression *)
- stepfield = 4 (* multiply by (Step[n] + Step[-n - 1]) *)
- thefunfield = 5 (* apply TheFunction to expression *)
- definitionfield = 6 (* apply the z-transform definition *)
-
- statevariables = 6
-
- initZstate[] := Table[True, {statevariables}]
-
-
- (* B E G I N R U L E B A S E *)
-
- (* MyZByPass--- called by forward DTFT and interfaces to MyZTransform *)
- MyZByPass[ f_, n_, z_, nlist_, zlist_, op_ ] :=
- Block [ {trans},
- completeOptions = op;
- dialogueAllFlag = SameQ[Replace[Dialogue, op], All];
- indentationString = " ";
- simplifyFlag = TrueQ[ Replace[Simplify, op] ];
- trans = MyZTransform[f, n, z, initZstate[], nlist, zlist, op];
- MakeZObject[ trans, z ] ]
-
- (* Interface to MyZTransform from ztransformdriver *)
- MyZTransform[ f_, n_, z_, nlist_, zlist_, op_ ] :=
- MyZTransform[ f, n, z, initZstate[], nlist, zlist, op ]
-
- (* Driver for one-dimensional rule base *)
- (* Loop until the expression to be transformed doesn't change *)
- MyZTransform[ f_, n_, z_, s_, nlist_, zlist_, op_ ] :=
- Block [ {discretef, laste, newe, newop, newzrules},
-
- (* make f discrete *)
- discretef = ToDiscrete[ f /. CStep[a_. n] :> Step[n] ];
-
- (* generate the z-transform rules *)
- newzrules = TransformFixUp[ n, z, op, forwardz, True,
- ZTransform, 0, Infinity ];
- ZTransformRules = Join[ newzrules,
- OriginalZTransformRules ];
-
- (* take the 1-D transform-- dialogueAllFlag is global *)
- newop = fixUp[op];
- newe = forwardz[discretef, n, z, s, nlist, zlist, newop];
- While [ ! SameQ[ laste, newe ],
- If [ dialogueAllFlag,
- Print[ indentationString, newe ];
- Print[ indentationString, "which becomes" ] ];
- laste = newe;
- newe = laste /. ( forwardz[a__] :>
- Replace[forwardz[a], ZTransformRules ] ) ];
- If [ dialogueAllFlag, Print[ indentationString, newe ] ];
-
- newe ]
-
-
- (* Format intermediate forms so that output from Dialogue -> All is readable *)
-
- Format[ antiCausalZ[t_, z_] ] :=
- SequenceForm[ {t}, Subscript[z -> z^-1], Subscript[" and flip ROC "] ]
-
- Format[ downsampleZ[t_, z_, m_, ___] ] :=
- SequenceForm[ {t},
- Subscript[" resample (ROC expands) "] ]
-
- Format[ dz[t_, z_:Global`z, k_:1] ] :=
- SequenceForm[ ColumnForm[ {"D" Superscript[k],
- " " ~StringJoin~ ToString[z]} ],
- { t } ]
-
- Format[ forwardz[ x_, n_, z_, s_, nlist_, zlist_, op_ ] ] :=
- SequenceForm[ ColumnForm[{"Z",
- " " ~StringJoin~ ToString[n]}],
- { x } ]
-
- Format[ multiplyByExponential[t_, aexp_, z_, c_, options_] ] :=
- c SequenceForm[ {t},
- Subscript[z -> z / aexp],
- Subscript[" and scale ROC "] ]
-
- Format[ propagateOperator[ztrans_, op_] ] := op [ ztrans ]
-
- Format[ upsampleZ[t_, z_, m_, ___] ] :=
- SequenceForm[ {t},
- Subscript[" resample (ROC shrinks) "] ]
-
- Format[ Zdz[t_, z_:Global`z, k_:1] ] :=
- SequenceForm[ ColumnForm[ {"Zdz" Superscript[k],
- " " ~StringJoin~ ToString[z]} ],
- { t } ]
-
-
- (* B E G I N R U L E S *)
-
-
- ZTransformRules = {}
-
- OriginalZTransformRules = {
-
-
- (* I. M U L T I D I M E N S I O N A L H O O K S *)
-
-
- (* A. Region of convergence specification for dimension given *)
- (* by the variable n. Allows multi-dimensional z-transforms *)
- (* like a^n1 Impulse[n1 - n2] Step[n1,n2] to be taken -- *)
- (* see definition for LineImpulsemDT in "TransSupport.m" *)
- forwardz[ SignalProcessing`ROCinfo[n_, rm_:0 , rp_:Infinity], n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- Transform[ 1, rm, rp ],
-
-
- (* B. Multidimensional line Impulses become LineImpulses. *)
- forwardz[ f_. Impulse[k_. n1_Symbol + l_. n2_Symbol], n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- forwardz[ f LineImpulse[{n1,n2}, {k,-l}],
- n, z, s, nlist, zlist, op ] /;
- SubsetQ[{n1, n2}, nlist] && MemberQ[{n1, n2}, n],
-
-
- (* C. Line impulses. *)
- forwardz[ f_. LineImpulse[varlist_, coefflist_], n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- Block [ {functionofn, zlistmD},
- functionofn = f /. varlist ~ReplaceWith~ (n / coefflist);
- zlistmD = AssociateItem[varlist, nlist, zlist];
- lineImpulseMDZ[forwardz[functionofn, n, z, s, nlist, zlist, op], z, zlistmD, Complement[varlist,{n}]] ] /;
- FreeQ[f, LineImpulse[a__]],
-
-
- (* D. Multinomials *)
- forwardz[ f_. Multinomial[n1_, nvars__], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {newfun},
- simplifyFlag = True; (* data global to this package *)
- newfun = f Binomial[Plus[n1, nvars],
- Apply[Times, Complement[{n1, nvars},{n}]]];
- forwardz[newfun, n, z, s, nlist, zlist, op] ] /;
- SubsetQ[{n1, nvars}, nlist] && MemberQ[{n1, nvars}, n],
-
- forwardz[ f_ (Plus[n1_, nvars__])!, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz[ myZmultinomialLeftOver[f, n1, nvars] Multinomial[n1, nvars],
- n, z, s, nlist, zlist, op ] /;
- SubsetQ[{n1, nvars}, nlist] && myZmultinomialQ[f, n1, nvars],
-
-
- (* E. Resampling *)
- (* 1. Upsampling *)
- forwardz[ Upsample[l_, nvars_List][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {dim, expr, i},
- dim = Length[nvars];
- expr = f;
- For [ i = 1, i <= dim, i++,
- expr = Upsample[ l[[i,i]], nvars[[i]] ][expr] ];
- forwardz[ expr, n, z, s, nlist, zlist, op ] ] /;
- mDresamplingCheck[separable, l, n, nvars, nlist],
-
- forwardz[ Upsample[l_, nvars_List][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- upsampleSetUp[ l, nvars, f, n, z, s, nlist, zlist, op ] /;
- mDresamplingCheck[Upsample, l, n, nvars, nlist],
-
-
- (* 2. Downsampling *)
- forwardz[ Downsample[m_, nvars_List][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {dim, expr, i},
- dim = Length[nvars];
- expr = f;
- For [ i = 1, i <= dim, i++,
- expr = Downsample[ m[[i,i]], nvars[[i]] ][expr] ];
- forwardz[ expr, n, z, s, nlist, zlist, op ] ] /;
- mDresamplingCheck[separable, m, n, nvars, nlist],
-
- forwardz[ Downsample[m_, nvars_List][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- downsampleSetUp[ m, nvars, f, n, z, s, nlist, zlist, op ] /;
- mDresamplingCheck[Downsample, m, n, nvars, nlist],
-
-
-
-
- (* II. R A T I O N A L Z - T R A N S F O R M S *)
-
-
- (* A. Lookup rules for the zero, step, and impulse functions. *)
- forwardz[ 0, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ 0, 0, Infinity ],
-
- forwardz[ Step[n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ 1 / ( 1 - z^-1 ), 1, Infinity ],
-
- forwardz[ Pulse[L_, n_ + n0_.], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ z^n0 ( 1 - z^(-L) ) / ( 1 - z^-1), 0, Infinity ] /;
- FreeQ[L, n] && FreeQ[n0, n],
-
- forwardz[ a_. ( Step[n_ + b_.] - Step[n_ + c_.] ), n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- allROC[subZ[forwardz[a Step[n + b], n, z, s, nlist, zlist, op],
- forwardz[a Step[n + c], n, z, s, nlist, zlist, op]]] /;
- ( b > c ),
-
- forwardz[ a_. Step[n_ + b_.] - a_. Step[n_ + c_.] + rest_, n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- addZ[allROC[subZ[forwardz[a Step[n + b], n, z, s, nlist, zlist, op],
- forwardz[a Step[n + c], n, z, s, nlist, zlist, op]]],
- forwardz[rest, n, z, s, nlist, zlist, op]] /;
- ( b > c ),
-
- forwardz[ a_. Impulse[n_ + n0_.], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ (a /. n -> -n0 ) z^n0, 0, Infinity ],
-
-
- (* B. Sinusoidal functions *)
- forwardz[ Sin[b_. + w_. n_] Step[n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ ( Sin[b] + Sin[w - b] z^-1 ) /
- ( 1 - 2 Cos[w] z^-1 + z^-2 ), 1, Infinity ] /;
- FreeQ[{b,w}, n], (* [Muth, 361] *)
-
- forwardz[ Cos[b_. + w_. n_] Step[n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ ( Cos[b] - Cos[w - b] z^-1 ) /
- ( 1 - 2 Cos[w] z^-1 + z^-2 ), 1, Infinity ] /;
- FreeQ[{b,w}, n], (* [Muth, 361] *)
-
- forwardz[ Sinh[b_. + w_. n_] Step[n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ ( Sinh[b] + Sinh[w - b] z^-1 ) /
- ( 1 - 2 Cosh[w] z^-1 + z^-2 ), 1, Infinity ] /;
- FreeQ[{b,w}, n], (* [Muth, 361] *)
-
- forwardz[ Cosh[b_. + w_. n_] Step[n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ ( Cosh[b] - Cosh[w - b] z^-1 ) /
- ( 1 - 2 Cosh[w] z^-1 + z^-2 ), 1, Infinity ] /;
- FreeQ[{b,w}, n], (* [Muth, 361] *)
-
-
- (* C. Binomial forms *)
- forwardz[ Binomial[n_, k_] Step[n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- Assuming[ k > 0, dialogueAllFlag ];
- Transform[ z^-k / (1 - z^-1)^(k + 1), 1, Infinity ] ] /;
- FreeQ[k, n] && Implies[NumberQ[k], (k > 0)], (* [Muth, 358] *)
-
- forwardz[ Binomial[k_, n_] a_^n_ b_^(k_ - n_) Step[n_], n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- Assuming[ k > 0, dialogueAllFlag ];
- Transform[ ( a z^-1 + b ) ^ k, -a/b, Infinity ] ] /;
- FreeQ[{a,b,k}, n] && Implies[NumberQ[k], (k > 0)], (* [Muth, 358] *)
-
-
- (* D. Expand definitions of multinomial forms *)
- forwardz[ f_ Multinomial[n_, r___], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {expandr, rlist},
- rlist = If [ EmptyQ[List[r]], {0}, ToList[r] ];
- expandr = Apply[ Times, Map[Factorial, rlist] ];
- forwardz [ f Plus[n, r] / ( n! expandr ), n, z,
- s, nlist, zlist, op ] ] /;
- FreeQ[{r}, n],
-
-
- (* E. Hybrid binomial/multinomial forms *)
- forwardz[ (n_ + k_ + j_.)! Step[n_] / n_!, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- Assuming[ k > 0, dialogueAllFlag ];
- Transform[ z^j k! / ( 1 - z^-1 )^(k + 1), 1, Infinity ] ] /;
- FreeQ[{k,j}, n] && Implies[NumberQ[k], (k > 0)], (* ???? *)
-
- forwardz[ Binomial[n_ + k_ + j_., k_] Step[n_], n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- Assuming[ k > 0, dialogueAllFlag ];
- Transform[ z^j / ( 1 - z^-1 )^(k + 1), 1, Infinity ] ] /;
- FreeQ[{k,j}, n] && Implies[NumberQ[k], (k > 0)], (* ???? *)
-
-
-
-
- (* III. N O N - R A T I O N A L Z - T R A N S F O R M S *)
-
-
- (* A. Denominators are rational functions of n *)
- forwardz[ Step[n_] / n_!, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ Exp[z^-1], 0, Infinity ], (* [Muth, 363] *)
-
- forwardz[ Step[n_] / ( a_ n_ + b_ ), n_, z_, s_, nlist_, zlist_, op_ ] :>
- scaleZ[forwardz[Step[n] / (n + b/a), n, z, s, nlist, zlist, op], 1/a] /;
- FreeQ[{a,b}, n], (* using (a (n + b/a)) fails when a = -1 *)
-
- forwardz[ Step[n_] / ( n_ + 1/2 ), n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ 2 Sqrt[z] ArcTan[z^-1], 0, Infinity ] /;
- FreeQ[a,n], (* [Muth, 363] *)
-
- forwardz[ Step[n_] / ( n_ + 1 ), n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ -z Log[ 1 - z^-1 ], 0, Infinity ], (* [Muth, 363] *)
-
- forwardz[ Step[n_] / ( 2 n_ )!, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ Cosh[ Sqrt[z^-1] ], 0, Infinity ], (* [Muth, 363] *)
-
- forwardz[ (2 n_)! Step[n_] / (2^n_ n_!)^2 , n_, z_, s_, nlist_, zlist_, op_ ] :>
- Transform[ Sqrt[ 1 / ( 1 - z^-1 ) ], 0, Infinity ], (* [Muth, 364] *)
-
-
- (* B. Family of Causal Linear Phase IIR Filters *)
- forwardz[ Step[n_] / ( Gamma[1 + n_] Gamma[r_ - n_] ), n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- Assuming[ Positive[r], dialogueAllFlag ];
- Transform[ (1 + z^-1)^(r - 1) / Gamma[r], 0, Infinity ] ] /;
- FreeQ[r, z] && Implies[ NumberQ[N[r]], N[r > 0] ], (* [ASSP, 480-482] *)
-
-
-
-
- (* IV. P R O P E R T I E S *)
-
-
- (* A. Homogeneity (pick off constants) *)
- forwardz[ c_ x_., n_, z_, s_, nlist_, zlist_, op_ ] :>
- scaleZ[forwardz[x, n, z, s, nlist, zlist, op], c] /;
- FreeQ[c,n] && ! ( SameQ[c,1] && SameQ[x,1] ), (* [O & S, 67] *)
-
- (* B. Additivity, resulting ROC is intersection of two ROC's *)
- forwardz[ x_+y_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- addZ[forwardz[x, n, z, s, nlist, zlist, op],
- forwardz[y, n, z, s, nlist, zlist, op]],
- (* [O & S, 67] *)
-
- forwardz[ (x_+y_)/c_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- addZ[forwardz[x/c, n, z, s, nlist, zlist, op],
- forwardz[y/c, n, z, s, nlist, zlist, op]],
- (* [O & S, 67] *)
-
-
- (* C. Shifts/delays -- every discrete function should be a *)
- (* function times either a Step or an Impulse, and the rule *)
- (* base already handles the Impulse case. *)
- forwardz[ f_. Step[n_ + m_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- scaleZ[ forwardz[(f /. n -> n - m) Step[n], n, z, s, nlist, zlist, op],
- z^m ] /;
- FreeQ[m, n],
-
- forwardz[ f_. Step[m_ - n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- scaleZ[ forwardz[(f /. n -> n + m) Step[-n], n, z, s, nlist, zlist, op],
- z^(-m) ] /;
- FreeQ[m, n],
-
- forwardz[ x_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {n0, xnorm},
- {n0, xnorm} = GetShiftFactor[x, n];
- xnorm = xnorm /. ( n -> n - n0 );
- scaleZ[ forwardz[xnorm, n, z, s, nlist, zlist, op], z^n0 ] ] /;
- ! SameQ[ First[ GetShiftFactor[x, n] ], 0 ],
-
-
- (* D. Anti-causal: x[n] --> X(z) ===> x[-n] --> X[1/z] *)
- forwardz[ x_. Step[-n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- antiCausalZ[forwardz[x Step[-n] /. n -> -n, n, z, s, nlist, zlist, op],
- z],
-
-
- (* E. Multiplication by n^m [Muth, 227] *)
- forwardz[ ZPolynomial[m_, n_] f_., n_, z_, s_, nlist_, zlist_, op_ ] :>
- scaleZ[ dz[ forwardz[ f, n, z, s, nlist, zlist, op ], z, m ],
- z^m ] /;
- FreeQ[m, n],
-
- forwardz[ n_^m_. x_., n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- Assuming[ m > 0, dialogueAllFlag ];
- If [ dialogueAllFlag, Print[ "where ", m, " is an integer" ] ];
- Zdz[ forwardz[x, n, z, s, nlist, zlist, op], z, m ] ] /;
- FreeQ[m,n] && Implies[NumberQ[m], IntegerQ[m] && ( m > 0 )],
-
-
- (* F. Integration [Muth, 231] *)
- forwardz[ x_ Step[n_ - 1] / n_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- integrateZ[scaleZ[subZ[ forwardz[x Step[n], n, z, s, nlist, zlist, op],
- Limit[x, n -> 0]],
- 1/z^2],
- z] /;
- ! InfinityQ[ Limit[x / n, n -> 0] ],
-
-
- (* G. Multiplication by c raised to an affine function of n, *)
- (* which covers exponential case. *)
- forwardz[ c_^(d_. (b_. + a_. n_)) x_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- multiplyByExponential [ forwardz[x, n, z, s, nlist, zlist, op],
- c^(a d), z, c^(b d), op ] /;
- FreeQ[{a,b,c,d}, n], (* [O & S, 67] *)
-
-
- (* H. Multiplication by a cosine function [Muth, 219] *)
- forwardz[ Cos[b_ + w_. n_] f_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz [ Cos[b] Cos[w n] f - Sin[b] Sin[w n] f,
- n, z, s, nlist, zlist, op ],
- forwardz[ Cos[a_. n_] f_., n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {trans},
- trans = forwardz[f, n, z, s, nlist, zlist, op];
- scaleZ [ addZ [ substituteforZ[trans, z, Exp[I a] z],
- substituteforZ[trans, z, Exp[-I a] z] ],
- 1/2] ] /;
- FreeQ[a,n],
-
-
- (* I. Multiplication by a sine function [Muth, 219] *)
- forwardz[ Sin[b_ + w_. n_] f_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz [ Sin[b] Cos[w n] f + Cos[b] Sin[w n] f,
- n, z, s, nlist, zlist, op ],
- forwardz[ Sin[a_. n_] f_., n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {trans},
- trans = forwardz[f, n, z, s, nlist, zlist, op];
- scaleZ [ subZ [ substituteforZ[trans, z, Exp[I a] z],
- substituteforZ[trans, z, Exp[-I a] z] ],
- I/2] ] /;
- FreeQ[a,n],
-
-
- (* J. Conjugation: Z{ Conj[x[n]] } --> Conj[ X ( Conj[z] ) ] *)
- forwardz[ Conjugate[x_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- conjZ[forwardz[x, n, z, s, nlist, zlist, op], z],
- (* [O&S, 67] *)
-
-
-
-
- (* V. D S P S T R U C T U R E S *)
-
-
- (* -. An operator independent of n--- take z-transform of f *)
- forwardz[ operator_[params__][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- propagateOperator[ forwardz[f, n, z, s, nlist, zlist, op],
- operator[params] ] /;
- FreeQ[{params}, n],
-
-
- (* A. Convolution *)
- forwardz[ Convolve[n_][x1_, x2_, rest__], n_, z_, s_, nlist_, zlist_, op_ ] :>
- multZ [ forwardz[x1, n, z, s, nlist, zlist, op],
- forwardz[Convolve[n][x2, rest], n, z, s, nlist, zlist, op] ],
-
- forwardz[ Convolve[n_][x1_, x2_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- multZ [ forwardz[x1, n, z, s, nlist, zlist, op],
- forwardz[x2, n, z, s, nlist, zlist, op] ],
-
- forwardz[ Convolve[nconv_List][x1_, x2_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- convolveZ[ Convolve[Complement[nconv, {n}]],
- forwardz[x1, n, z, s, nlist, zlist, op],
- forwardz[x2, n, z, s, nlist, zlist, op] ] /;
- MemberQ[nconv, n],
-
-
- (* B. Difference equations [Muth, 224] *)
- forwardz[ Difference[m_, n_][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- Assuming[ m > 0, dialogueAllFlag ];
- If [ dialogueAllFlag, Print[ "where ", m, " is an integer" ] ];
- scaleZ[ forwardz[f, n, z, s, nlist, zlist, op],
- ( 1 - z^-1 ) ^ m ] ] /;
- FreeQ[m,n] && Implies[NumberQ[m], IntegerQ[m] && m > 0],
-
- (* C. Downsampling *)
-
- (* 1. Downsampling operator [Crochiere & Rabiner, 34] *)
- forwardz[ Downsample[m_,n_][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- If [ dialogueAllFlag,
- Print[ "assuming ", m, " is an integer" ] ];
- downsampleZ[ forwardz[f, n, z, s, nlist, zlist, op], z, m ] ] /;
- FreeQ[m,n] && Implies[ NumberQ[m], IntegerQ[m] ] ,
-
- (* 2. Rewrite functions that are really downsampled *)
- (* This relies on the function ScalingFactor which works *)
- (* best after an expression has been fully expanded. *)
- forwardz[ f_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {m},
- m = computeDownsamplingFactor[f, n];
- If [ dialogueAllFlag && ! IntegerQ[m],
- Print[ "assuming ", m, " is an integer" ] ];
- forwardz[ Downsample[m, n][ f /. n -> (n/m) ],
- n, z, s, nlist, zlist, op ] ] /;
- reallyDownsampledQ[f, n],
-
-
- (* D. Digital FIR filters. *)
- forwardz[ FIR[n_, h_, firop___], n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz[SequenceToFunction[ToList[h], n],
- n, z, s, nlist, zlist, op],
-
- forwardz[ FIR[n_, h_, firop___] [ x__ ], n_, z_, s_, nlist_, zlist_, op_ ] :>
- multZ [ forwardz[FIR[n, h, firop], n, z, s, nlist, zlist, op],
- forwardz[x, n, z, s, nlist, zlist, op] ],
-
- (* E. Digital IIR filters. *)
- (* Region of convergence is incorrect. *)
- forwardz[ IIR[n_, a_List, iirop___], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {denom, len, poles},
- len = Length[a];
- denom = a[[1]] -
- Sum[a[[index+1]] z^(- index), {index, 1, len - 1}];
- poles = GetRootList[denom, z];
- { 1 / denom, Max[Abs[poles]], Infinity } ] /;
- VectorQ[a],
-
- forwardz[ IIR[n_, a_, iirop___] [ x__ ], n_, z_, s_, nlist_, zlist_, op_ ] :>
- multZ [ forwardz[IIR[n, a, iirop], n, z, s, nlist, zlist, op],
- forwardz[x, n, z, s, nlist, zlist, op] ],
-
- forwardz[ IIRFunction[n_, a_, x_, h_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- multZ [ forwardz[IIR[n, a], n, z, s, nlist, zlist, op],
- forwardz[x, n, z, s, nlist, zlist, op] ],
-
- (* F. Imaginary part of a sequence [O&S, 67] *)
- forwardz[ Im[x_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {trans},
- trans = forwardz[x, n, z, s, nlist, zlist, op];
- scaleZ [ addZ [ trans,
- substituteforZ[trans, z, Conjugate[z]] ],
- 1/2] ],
-
- (* G. Periodic sequence with period k samples [Muth, 232] *)
- forwardz[ Periodic[k_,n_][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {fk, ntemp},
- Assuming[ k > 0, dialogueAllFlag ];
- If [ dialogueAllFlag && ! IntegerQ[k],
- Print[ "where ", k, " is an integer" ] ];
-
- fk = If [ NumberQ[k],
- SequenceToFunction[ Table[f /. n -> ntemp,
- {ntemp, 0, k-1}],
- n ],
- f Pulse[k, n] ];
-
- scaleZ [ forwardz[fk, n, z, s, nlist, zlist, op],
- 1 / ( 1 - z^(-Abs[k]) ) ] ] /;
- FreeQ[k,n] && Implies[NumberQ[k], IntegerQ[k] && k > 0],
-
- (* H. Real part of a sequence [O&S, 67] *)
- forwardz[ Re[x_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {trans},
- trans = forwardz[x, n, z, s, nlist, zlist, op];
- scaleZ [ addZ [ trans,
- substituteforZ[trans, z, Conjugate[z]] ],
- -I/2] ],
-
- (* I. Reverse operator ?ROC? *)
- forwardz[ Rev[n_][x_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- antiCausalZ[forwardz[x, n, z, s, nlist, zlist, op], z],
-
-
- (* J. Shift operator *)
- forwardz[ Shift[m_,n_][x_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- If [ dialogueAllFlag && ! IntegerQ[m],
- Print[ "assuming ", m, " is an integer" ] ];
- scaleZ[forwardz[x, n, z, s, nlist, zlist, op], z^(-m)] ] /;
- FreeQ[m,n] && Implies[NumberQ[m], IntegerQ[m]],
-
-
- (* K. Signum function *)
- forwardz[ f_. Sign[g_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz[ f Step[g] - f Step[-g], n, z, s, nlist, zlist, op ] /;
- ! FreeQ[f, n],
-
-
- (* L. Summation *)
- forwardz[ Summation[i_,0,n_,1][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- scaleZ[ forwardz[f, n, z, s, nlist, zlist, op], 1 / ( 1 - z^-1 ) ] /;
- FreeQ[i, n], (* [Muth, 255] *)
-
- forwardz[ Summation[i_,il_,iu_,inc_][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz[ Summation[i, 0, Expand[iu - il], inc][f /. i -> i + il],
- n, z, s, nlist, zlist, op ] /;
- FreeQ[{i, inc}, n] && (! FreeQ[il, n]) && (! FreeQ[iu, n]) &&
- FreeQ[Expand[iu - il], n],
-
- (*
- forwardz[ Summation[i_,il_,iu_,inc_][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- propagateOperator[ forwardz[f, n, z, s, nlist, zlist, op],
- Summation[i, il, iu, inc] ] /;
- FreeQ[{i, il, iu, inc}, n],
- *)
-
-
- (* M. Upsampling [Crochiere & Rabiner, 36] *)
- forwardz[ Upsample[m_,n_][f_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- If [ dialogueAllFlag && ! IntegerQ[m],
- Print[ "assuming ", m, " is an integer" ] ];
- upsampleZ[ forwardz[f, n, z, s, nlist, zlist, op], z, m ] ] /;
- FreeQ[m,n] && Implies[ NumberQ[m], IntegerQ[m] && ( m > 0 ) ],
-
-
-
-
- (* V. S T R A T E G I E S *)
-
-
- (* A. Handle affine step functions. *)
- forwardz[ f_. Step[k_ n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {},
- If [ dialogueAllFlag && ! IntegerQ[k],
- Print[ "assuming ", k, " is an integer" ] ];
- forwardz[ f Step[n], n, z, s, nlist, zlist, op ] ] /;
- Implies[ NumberQ[k], IntegerQ[k] ],
-
-
- (* A. Remove any time-dependent Abs functions *)
- forwardz[ f_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz[ absDialogue[f, n, op], n, z,
- SetStateField[s, stepfield, False],
- nlist, zlist, op ] /;
- GetStateField[s, stepfield] && ! FreeQ[ f, Abs[n] ],
-
-
- (* B. Collect exponential terms *)
- forwardz[ f_. a_^(t_. n_ + k_.) / b_^(u_. n_ + l_.), n_, z_,
- s_, nlist_, zlist_, op_ ] :>
- forwardz[ (a^t/b^u)^n f a^k/b^l, n, z, s, nlist, zlist, op ],
-
-
- (* C. Handle functions which "blow up" at origin *)
- forwardz[ x_ Step[n_] / n_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz[ Limit[x / n, n -> 0] Impulse[n] + x Step[n-1] / n, n, z,
- s, nlist, zlist, op ] /;
- ( Limit[x, n -> 0] == 0 ),
-
-
- (* D. Expand out product terms like (n + 1) (n + 2) ... *)
- forwardz[ x_Times, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz [ Distribute[x], n, z, s, nlist, zlist, op ] /;
- ! SameQ[x, Distribute[x]],
-
-
- (* E. Factor denominator *)
- forwardz[ x_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz [ Numerator[x] / Factor[Denominator[x]], n, z,
- SetStateField[s, factorfield, False],
- nlist, zlist, op ] /;
- GetStateField[s, factorfield] && RationalFunctionQ[x, n],
-
-
- (* F. Expand out numerator terms *)
- forwardz[ x_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz [ Expand[x], n, z,
- SetStateField[s, expandfield, False],
- nlist, zlist, op ] /;
- GetStateField[s, expandfield] && ! SameQ[x, Expand[x]],
-
-
- (* G. Expand out numerator and denominator terms *)
- forwardz[ x_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- forwardz [ ExpandAll[x], n, z,
- SetStateField[s, expandallfield, False],
- nlist, zlist, op ] /;
- GetStateField[s, expandallfield] && ! SameQ[x, ExpandAll[x]],
-
-
- (* H. Use the definition *)
- forwardz[ x_ Step[n_], n_, z_, s_, nlist_, zlist_, op_ ] :>
- applyDefinition[x, n, z, s, nlist, zlist, op] /;
- GetStateField[s, definitionfield] && Replace[Definition, op],
-
-
- (* I. Two-sided transform *)
- forwardz[ x_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {state, trans},
- state = SetStateField[s, stepfield, False];
- trans = MyZTransform[ x Step[n] + x Step[-n - 1],
- n, z, state, nlist, zlist, op ];
- If [ TrueQ[ZForm[trans] && TheFunction[trans] != 0],
- If [ InformUserQ[op],
- Message[Transform::twosided, x] ];
- trans,
- forwardz[ x, n, z, state, nlist, zlist, op ] ] ] /;
- GetStateField[s, stepfield],
-
-
- (* J. Put all signal processing objects into mathematical form *)
- forwardz[ x_, n_, z_, s_, nlist_, zlist_, op_ ] :>
- Block [ {newx, state},
- newx = ToDiscrete [ TheFunction[x] ];
-
- state = If [ SameQ[newx, x], s, initZstate[] ];
- state = SetStateField[state, thefunfield, False];
- state = SetStateField[state, stepfield, False];
-
- forwardz [ newx, n, z, state, nlist, zlist, op ] ] /;
- GetStateField[s, thefunfield]
-
- }
-
-
- (* E N D R U L E S *)
-
-
-
- (* E N D P A C K A G E *)
-
-
- End[]
- EndPackage[]
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- On[ General::spell ];
- On[ General::spell1 ] ];
-
-
- (* H E L P I N F O R M A T I O N *)
-
- Combine[ SPfunctions, { ZTransform } ]
- Protect[ ZTransform ]
-
-
- (* E N D I N G M E S S A G E *)
-
- Print["The forward z-transform rules have been loaded."]
- Null
-